import copy
from typing import Any

from flask import Flask


class AbsCtx(object):
    app: Flask = None
    # 其他
    task_id: str = None
    begin_time: float = None
    end_time: float = None
    # 执行异常
    exception: Any = None


class XycContext(AbsCtx):
    """
    预测 上下文
    """
    # 参数
    # 要预测时间
    predict_date: str | None = None
    # 输入数据
    in_data: Any = []

    # 响应
    out_data: Any = []


class EquInfo(object):
    """
    设备信息
    """
    equCode: str | None = None
    equType: str | None = None
    loc: str | None = None
    # 设备状态 1可用 2不可用
    status: str | None = None
    workType: str | None = None

    def __init__(self, equCode: str, equType: str, loc: str, status: str, workType: str):
        self.equCode: str = equCode
        self.equType: str = equType
        self.loc: str = loc
        self.status: str = status
        self.workType: str = workType

    @property
    def uk(self):
        """
        唯一值
        :return:
        """
        return self.gen_uk(self.equType, self.equCode)

    @staticmethod
    def gen_uk(equ_type, equ_code) -> str:
        return f'{equ_type}_{equ_code}'

    @property
    def ext_loc(self) -> Any:
        """
        设备位置LOC
        :return:
        """
        from x_pc.model.model import Loc

        eloc = Loc(self.loc)
        if not eloc or not eloc.lane:
            return self.loc
        return eloc

    @property
    def is_valid(self):
        """
        设备是否有效
        :return:
        """
        return self.status and (self.status == "1" or self.status == 1)


class WorkStationInfo(object):
    """
    当前设备 (equ_type + equ_code) 可执行的 作业类型
    """
    equType: str | None = None
    equCode: str | None = None
    workTypeList: list[str] = []

    def __init__(self, equType: str, equCode: str, workTypeList: list[str], *args, **kwargs):
        self.equType: str = equType
        self.equCode: str = equCode
        self.workTypeList: list[str] = workTypeList


class StorerDeliverLayer(object):
    """
    交付对象 (出货口)楼层信息
    """

    B1_FLAG = '01'
    F1_FLAG = '02'

    ZZ_FLAG = 'ZZ'
    EMS_FLAG = 'EMS'

    # 交付对象代码
    deliver_code: str | None = None
    # 交付对象类型 EMS/ZZ
    deliver_type: str | None = None
    floor_level: str | None = None
    # 指定交付口
    raw_designate_outlets: list[str] = []
    designate_outlets: list[str] = []
    designate_equtype: str | None = None

    def __init__(self, **kwargs):
        self.deliver_code = kwargs.get('storerkey')
        self.deliver_type = kwargs.get('address1')
        self.floor_level = self._parse_address2(kwargs.get('address2'))
        self.designate_outlets = []
        if 'address3' in kwargs and kwargs['address3']:
            self.designate_outlets = kwargs['address3'].split(',')
            self.raw_designate_outlets = copy.copy(self.designate_outlets)

    def __str__(self):
        if self.designate_outlets:
            return f'{self.deliver_code} ({self.deliver_type}) {self.floor_level} --> {self.designate_outlets}'
        return f'{self.deliver_code} ({self.deliver_type}) {self.floor_level}'

    def __repr__(self):
        return self.__str__()

    @staticmethod
    def _parse_address2(addr: str) -> str:
        """
        判断出货口类型
        "是"/"否"/"Y"/"N"/"null"/" "  --> 1楼默认出货口
        # 具体值
        "01" --> -1楼出货口
        “02” --> 1楼出货口
        "03" --> 2楼
        """
        addr = addr.strip() if addr else addr
        if addr and addr.isdigit():
            return addr
        return StorerDeliverLayer.F1_FLAG

    def flag(self):
        """
        标识
        如：ZZ-01 即：自制-1
        """
        return f'{self.deliver_type}-{self.floor_level}'

    def is_zz(self):
        """
        是否为自制
        """
        return self.deliver_type == StorerDeliverLayer.ZZ_FLAG

    def is_ems(self):
        """
        是否为EMS
        """
        return self.deliver_type == StorerDeliverLayer.EMS_FLAG

    def is_b1(self):
        """
        是否为-1层
        """
        return self.floor_level == StorerDeliverLayer.B1_FLAG

    def is_f1(self):
        """
        是否为1楼
        """
        return self.floor_level == StorerDeliverLayer.F1_FLAG


class XpcContext(AbsCtx):
    """
    排程 上下文
    """
    # 发货任务Ids
    deliveryTaskIdList: list[str] = []
    # 在库任务Ids
    interiorTsakIdList: list[str] = []
    # 预作业任务Ids
    preworkTsakIdList: list[str] = []
    # 理货任务Ids
    tallyTsakIdList: list[str] = []

    # 锁定任务ids
    pendingTaskIdList: list[str] = []

    # 所有设备数据
    allEquInfo: list[dict] = []

    # 基准时间
    baseDateTime: str = None

    # 类似 allEquInfo, 但主要记录 当前设备可以做哪些类型的任务
    workStationInfo: list[dict] = []

    # 交付对象列表
    storerList: list[StorerDeliverLayer] = []

    result: dict = {}


class XpmContext(AbsCtx):
    """
    排模 上下文
    """
    # 要排模的 (巷道)标识
    zone_list: list[str] = []
    # 要排模的标识 (HTTP请求原始参数)
    raw_zone_list: list[str] = []

    @property
    def fixed_raw_zone_list(self) -> str:
        """
        格式化以存储，使用【,】逗号分割，为空 则使用ALL
        :return:
        """
        if not self.raw_zone_list:
            return 'ALL'
        return ','.join(self.raw_zone_list)


class XtwContext(AbsCtx):
    # 输入数据
    in_data: Any = []
    # 输入数据
    response_message: str | None = None

    result: dict = {}
    """
    时间窗 上下文
    """
    pass
